# 分类管理的类
import os
import json
import re
import logging
from typing import List, Optional

# 导入统一的日志配置模块
from log_config import setup_logging
# 导入接口定义
from interfaces.category_manager import ICategoryManager

# 配置日志
setup_logging()
logger = logging.getLogger(__name__)


class CategoryManager(ICategoryManager):
    def __init__(self, category_dir: str, category_file: str):
        self.category_dir = category_dir
        self.category_file = category_file
        self.category_path = os.path.join(self.category_dir, self.category_file)

        if not os.path.exists(category_dir):
            logger.info(f"启动时创建 categories 目录: {category_dir}")
            os.makedirs(category_dir)
        else:
            logger.info(f"categories 目录已存在: {category_dir}")

        if not os.path.exists(self.category_path):
            logger.info(f"启动时创建 categories/category.json 文件: {category_file}")
            with open(self.category_path, "w", encoding='utf-8') as f:
                json.dump([{"name": "default", "desc": "默认分类"}], f, ensure_ascii=False, indent=2)
        else:
            logger.info(f"categories/category.json 文件已存在: {category_file}")

        # 检查 default 分类是否存在
        category = self.get_all_categories()
        name_list = [item['name'] for item in category]
        if 'default' not in name_list:
            # 添加 default 分类
            category.append({"name": "default", "desc": "默认分类"})
            with open(self.category_path, 'w', encoding='utf-8') as f:
                json.dump(category, f, ensure_ascii=False, indent=2)
            logger.info(f"categories/category.json 文件中添加 default 分类.")

    def get_all_categories(self) -> List[str]:
        # 从文件中加载分类数据
        try:
            with open(self.category_path, 'r', encoding='utf-8') as f:
                categories = json.load(f)
                return categories
        except Exception as e:
            logger.error(f"加载分类文件失败: {str(e)}")
            return []
    
    # 检查某个 name 是否合法
    def valid_name(self, name: str):
        result = { "success": False, "message": "" }
        categories = self.get_all_categories()
        name_list = [item['name'] for item in categories]
        if name in name_list or name == 'default':
            result["message"] = "分类名称已存在. "
        if len(name) > 64:
            result["message"] +=  "分类名称长度不能超过64个字符. "
        # 检查首字符
        if not re.match(r'^[a-zA-Z_]', name):
            result["message"] += "集合名称首字符必须是字母(a-z, A-Z)或下划线(_). "    
        # 检查所有字符（首字符已验证，这里检查剩余字符）
        if not re.fullmatch(r'^[a-zA-Z_][a-zA-Z0-9_\-]*$', name):
            result["message"] += "集合名称包含不允许的字符,仅允许字母、数字、下划线(_)和连字符(-). "
        # 检查是否包含非ASCII字符（如中文、特殊符号等）
        if not name.isascii():
            result["message"] += "集合名称不允许包含中文或非ASCII字符. "
        
        if result["message"] == "":
            result["success"] = True
        return result 

    # 添加新的元素
    def add_category(self, category: str) -> bool:
        """添加新分类"""
        desc = ""
        current_categories = self.get_all_categories()
        try:
            result = self.valid_name(category)
            if not result["success"]:
                logger.error(f"添加分类失败: {result['message']}")
                return False
            current_categories.append({"name": category, "desc": desc})
            with open(self.category_path, 'w', encoding='utf-8') as f:
                json.dump(current_categories, f, ensure_ascii=False, indent=2)
            logger.info(f"成功添加分类: {category}")
            return True
        except ValueError as e:
            logger.error(f"添加分类失败: {str(e)}")
            return False
        except Exception as e:
            logger.error(f"添加分类时发生错误: {str(e)}")
            return False
    
    # 兼容原有代码的带描述添加分类方法
    def add_category_with_desc(self, name: str, desc: str) :
        category = self.get_all_categories()
        try:
            result = self.valid_name(name)
            if not result["success"]:
                raise ValueError(result["message"])
            category.append({"name": name, "desc": desc})
            with open(self.category_path, 'w', encoding='utf-8') as f:
                json.dump(category, f, ensure_ascii=False, indent=2)
            logger.info(f"成功添加分类: {name}")
        except ValueError as e:
            logger.error(f"添加分类失败: {str(e)}")
            raise ValueError(str(e))
        except Exception as e:
            logger.error(f"添加分类失败: {str(e)}")
            raise ValueError(str(e))

    def delete_category(self, category: str) -> bool:
        """删除分类"""
        try:
            if category == 'default':
                logger.warning("尝试删除默认分类，操作被拒绝")
                return False
            current_categories = self.get_all_categories()
            old_len = len(current_categories)
            new_categories = [item for item in current_categories if item["name"] != category]
            new_size = len(new_categories)
            if old_len == new_size:
                logger.warning(f"分类 {category} 不存在")
                return False
            
            with open(self.category_path, 'w', encoding='utf-8') as f:
                json.dump(new_categories, f, ensure_ascii=False, indent=2)
            logger.info(f"成功删除分类: {category}")
            return True
        except Exception as e:
            logger.error(f"删除分类时发生错误: {str(e)}")
            return False
    
    # 兼容原有代码的删除分类方法
    def remove_category(self, name: str):
        try:
            if name == 'default':
                raise ValueError("不能删除默认分类.")
            category = self.get_all_categories()
            old_len = len(category)
            new_category = [item for item in category if item["name"] != name]
            new_size = len(new_category)
            if old_len == new_size:
                raise ValueError(f"分类 {name} 不存在.")
            
            with open(self.category_path, 'w', encoding='utf-8') as f:
                json.dump(new_category, f, ensure_ascii=False, indent=2)
            logger.info(f"成功删除分类: {name}")
        except ValueError as e:
            raise ValueError(str(e))
        except Exception as e:
            raise ValueError(str(e))
    
    def is_category_exist(self, category: str) -> bool:
        """检查分类是否存在"""
        categories = self.get_all_categories()
        return any(item["name"] == category for item in categories)
    
    def save_categories(self) -> bool:
        """保存分类到持久化存储"""
        # 在当前实现中，添加和删除操作已经实时保存到文件
        # 此方法主要是为了满足接口要求
        try:
            # 重新获取并保存分类，确保数据一致性
            categories = self.get_all_categories()
            with open(self.category_path, 'w', encoding='utf-8') as f:
                json.dump(categories, f, ensure_ascii=False, indent=2)
            logger.info("分类数据已保存")
            return True
        except Exception as e:
            logger.error(f"保存分类数据失败: {str(e)}")
            return False
    
    def load_categories(self) -> bool:
        """从持久化存储加载分类"""
        # 在当前实现中，获取分类时已经实时从文件加载
        # 此方法主要是为了满足接口要求
        try:
            self.get_all_categories()
            logger.info("分类数据已加载")
            return True
        except Exception as e:
            logger.error(f"加载分类数据失败: {str(e)}")
            return False
